// $Id: wave.jjt,v 1.45 2005/06/18 04:58:18 iradu Exp $    -*-Java-*-
// ===========================================================================
//
// (history at end)

options {
    STATIC = false;
    MULTI = true;
    VISITOR = true;
}

PARSER_BEGIN(WAVEParser)

package ast;
////////////////////////////////////////////////////////////////
// HINT for javac error-messages refering to wave.jj:
// add 7 to find line in this file
////////////////////////////////////////////////////////////////

/**
 * Class WAVEParser is responsible for parsing a WAVE-program from a
 * WAVE file. It is loosely based on the grammer given in the Appendix of
 * Peter Sapaty, Mobile Processing in Distributed and Open Environments,
 * John Wiley & Sons, 1999, and Peter Borst, Entwurf und Inplementierung
 * eines Interpreters fuer die Logikfluss--Sprache WAVE, Diplomarbeit
 * Universitaet Karlsruhe, 1990.
 *
 * @version     $Revision: 1.44 $
 * @author      Kai S. Juse
 */
public class WAVEParser {

   /**
    * Reads from stadard input and tries to parse a "WAVEProgram". Just as a
    * simple test and demo.
    */
    public static void main(String args[]) {
	System.err.println("Reading a \"WAVEProgram\" from standard input...");
	WAVEParser p = new WAVEParser(System.in);
	try {
	    SimpleNode wave = p.Wave();
	    wave.dump(" ");
	    System.err.println("Thank you.");
	} catch (Exception e) {
	    System.out.println("Oops.");
	    System.out.println(e.getMessage());
	    e.printStackTrace();
	}
    }

   final public String WaveTail() {
      return m_waveTail;
   }

   private String m_waveTail;
}

PARSER_END(WAVEParser)


//======================================================================
// Scanner definitions

TOKEN: {
    <INTEGER: (<DIGIT>)+>
  | <STRING: "`" (~["`","\n","\r"])*"'" 
		  | (["a"-"z","_"] (<LETTER> | <DIGIT>)*)>
  | <#LETTER: ["a"-"z","A"-"Z","_"]>
  | <#DIGIT: ["0"-"9"]>
  | <BRACKET: "{" (~["\n", "\r", "{", "}"])* "}">
}

// Rules
TOKEN: {
    <SEQ: "SEQUENCE" | "SQ">
  | <PAR: "PARALLEL" | "PA">
  | <OR_SEQ: "OR_SEQUENTIAL" | "OS">
  | <OR_PAR: "OR_PARALLEL" | "OP">
  | <AND_SEQ: "AND_SEQUENTIAL" | "AS">
  | <AND_PAR: "AND_PARALLEL" | "AP">
  | <RANDOM: "RANDOM" | "RN">
  | <REPEAT: "REPEAT" | "RP">
  | <WAIT: "WAIT" | "WT">
  | <INDIV: "INDIVISIBLE" | "ID">
  | <CREATE: "CREATE" | "CR">
  | <RELEASE: "RELEASE" | "RL">
}

// Environmental Variables
TOKEN: {
    <CONTENT: "CONTENT" | "C">
  | <ADDRESS: "ADDRESS" | "A">
  | <PRED: "PREDECESSOR" | "P">
  | <LINK: "LINK" | "L">
  | <ORIENT: "ORIENTATION" | "O">
  | <TERM: "TERMINAL" | "T">
  | <IDENT: "IDENTITY" | "I">
  | <ENTRY: "ENTRY" | "E">
  | <VICINITY: "VICINITY" | "V">
  | <DNEIGHBOURS: "DNEIGHBOURS" | "DN">
  | <MAP: "MAP" | "M">
  | <GRAPH: "GRAPHICS" | "G">
}

// Constants
TOKEN: {
    <ANY: "ANY">
  | <ALL: "ALL">
  | <DIRECT: "DIRECT" | "@">
  | <INFIN: "INFINITE" | "INF">
  | <STAY: "STAY">
  | <NONE: "NONE">
  | <ABORT: "ABORT"> // | "3">
  | <TRUE: "TRUE"> // | "2">
  | <DONE: "DONE"> // | <"1">
  | <FALSE: "FALSE"> // | <"0">
  | <IP: "$$">
}

// Operators
TOKEN: {
    <HASH: "#">
  | <DHASH: "##">
  | <MHASH: "-#">
  | <PHASH: "+#">
  | <BANG: "!">
  | <ASSIGN: "=">
  | <GT: ">">
  | <LT: "<">
  | <CONTAINS: "~">
  | <NCONTAINS: "/~">
  | <HOOK: "?">
  | <POW: "^">  
  | <COLON: ":">
  | <DCOLON: "::">
  | <EQ: "==">
  | <LE: "<=">
  | <GE: ">=">
  | <NE: "/=">
  | <PLUS: "+">
  | <MINUS: "-">
  | <STAR: "*">
  | <SLASH: "/">
  | <AMP: "&">
  | <PERCENT: "%">
  | <BAR: "|">
  | <DGT: ">>">  
}


TOKEN : // Seperators
{
    <LPAREN: "(">
  | <RPAREN: ")">
  | <COMMA: ",">
  | <DOT: ".">
  | <SEMICOLON: ";">
}

TOKEN: {
    <FRONTAL: "F" (<LETTER> | <DIGIT>)*>
  | <NODAL: "N" (<LETTER> | <DIGIT>)*>
}

// white spaces and C/C++ style comments
SKIP :
{
    " "
  | "\t"
  | "\n"
  | "\r"
  | "\f"
  | "\\\n"
  | "\\\r\n"
  | <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
  | <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/">
}

//======================================================================
// WAVE grammar
SimpleNode Wave() #WAVEProgram :
{}
{
   Zone() (<DOT> Zone())* <EOF>
      { return jjtThis; }
}

SimpleNode WaveHead() #WAVEProgram :
{}
{
   Zone()
      {
	 m_waveTail = "";
	 Token t;
	 for(t=token_source.getNextToken(); t.kind != 0 ;t=token_source.getNextToken())
	 {
	    m_waveTail += t.toString();
	 }
	 return jjtThis;
      }
}

void Zone() #void :
{}
{
   (Sector() (<COMMA> Sector())*) #Zone
}

void Sector() #void:
{}
{
   // to destinguish <"SIGN"> <INTEGER> <==> and <"SIGN"> <INTEGER> <HASH>
   LOOKAHEAD(3)
   Action() #Sector
  |
   Rule() #Sector
  |
   (<LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #ZoneList
  |
   Move() #Sector
// Move at end, because it can be empty
}

void Rule() #void:
{}
{
   (<SEQ> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Seq
  |
   (<PAR> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Parallel
  |
   (<OR_SEQ> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #OrSequential
  |
   (<AND_SEQ> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #AndSequential
  |
   (<OR_PAR> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #OrParallel
  |
   (<AND_PAR> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #AndParallel
  |
   (<INDIV> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Indivisible
  |
   (<CREATE> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Create
  |
   (<WAIT> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Wait
  |
   // Repeat has only one argument: a list of Zones
   // written inline to avoid intermediate WAVEProgram node
   (<REPEAT> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Repeat   
  | 
  (<RANDOM> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Random  
  | 
  (<RELEASE> <LPAREN> (Zone() (<DOT> Zone())*) <RPAREN>) #Release
}
// not exacty as in thesis
void Move() #void:
{}
{ 
    LOOKAHEAD(2)
    Hop()
  |
    LOOKAHEAD(<COMMA> | <DOT> | <RPAREN> | <EOF>)
	{
	    // just to find the code in WAVEParser.java
	    boolean nothing_to_do_for_an_EmptyMove;
	}#EmptyMove  
}

// SpatialRValues:
void Unit() #void:
{}
{
  LOOKAHEAD(SpatialVar() <IP> Ip())
	(SpatialVar() <IP> Ip()) #IpAddress
  |
    EnvRValue()
  |
    LOOKAHEAD(2) // to find <NODAL> _<SEMICOLON>_
    SpatialVar()
  |
    LOOKAHEAD(ArrayLiteral() <SEMICOLON>) // accumulate as much as possible
    ( ArrayLiteral() (<SEMICOLON> ArrayLiteral())* ) #ArrayConst(>1)
    
  |  
	LOOKAHEAD(SimpleLiteral() <IP> Ip())
	(SimpleLiteral() <IP> Ip()) #IpAddress  
	
  |  
    SimpleLiteral()
  
  
}

void Ip() #void:
{}
{
	StringConst()
    |
    SpatialVar()

}

void Action() #void:
{}
{
   <TRUE><BANG>#StopTrue | <DONE><BANG> #StopDone| <ABORT><BANG> #StopAbort| <FALSE><BANG> #StopFalse | <BANG> #Stop
  |
   <STAY> #Stay
  |
   (<HOOK> Unit())#SysCall  
  |
   (<POW> TaskVar())#FunctionCall
  |
   SpecialAssign()
  |
   LOOKAHEAD(2)
   Unit() (
	    (LOOKAHEAD(2)
	     (<LT> Unit()) #LessThan(2) | <LT> #LessThan(1))
	 |
	    (LOOKAHEAD(2)
	     (<LE> Unit()) #LessEqual(2) | <LE> #LessEqual(1))
	 |
	    (LOOKAHEAD(2)
	     (<EQ> Unit()) #Equals(2) | <EQ> #IsUndefined(1))
	 |
	    (LOOKAHEAD(2)
	     (<NE> Unit()) #NotEquals(2) | <NE> #IsDefined(1))
	 |
	    (LOOKAHEAD(2)
	     (<CONTAINS> Unit()) #Contains(2) | <CONTAINS> #Contains(1))
	    // Contains(1) is in fact another way to say IsUndefiend (?)
	 |
	    (LOOKAHEAD(2)
	     (<NCONTAINS> Unit()) #NotContains(2) | <NCONTAINS> #NotContains(1))
	    // NotContains(1) is in fact another way to say IsDefiend (?)
	 |
	    (LOOKAHEAD(2)
	     (<GE> Unit() #GreaterEqual(2)) | <GE> #GreaterEqual(1))
	 |
	    (LOOKAHEAD(2)
	     (<GT> Unit()) #GreaterThan(2) | <GT> #GreaterThan(1))
	 |
	    (<HOOK> Unit()) #SysCall(2)
	    )
  |
   // Allows code like: 'N1:1 = 12'  
   LOOKAHEAD(3)
   SpatialVar() Subscript() Assign()
  | 
   // Allows code like: 'N1::1 = 12'
   LOOKAHEAD(3)  
   SpatialVar() IndexOf() Assign()
  |
 

   // Allows code like: 'N1 = Fa::Fb'
   LOOKAHEAD(SpatialVar() <ASSIGN> SpatialVar() <DCOLON>)
   SpatialVar() Assign() AssignIndexOf()

  |
   // Allows code like: 'N1 = Fa:Fb'
   LOOKAHEAD(SpatialVar() <ASSIGN> SpatialVar() <COLON>)
   SpatialVar() Assign() AssignSubscript()
  |
   LOOKAHEAD(3)
   SpatialVar() (
	     Assign()
	 |
	     Concat()
	 |
	     Join()
	 |
	     Split()
	 |
	     Subscript()
	 |
	     IndexOf()
	 |
	     Sum()
	 |
	     Difference()
	 |
	     Product()
	 |
	     Quotient()
	    )
}

void Product() #void:
{}
{
   LOOKAHEAD(2)
    (<STAR> Unit()) #Product(2)
   |
    <STAR> #Product(1)
}

void Quotient() #void:
{}
{
   LOOKAHEAD(2)
    (<SLASH> Unit()) #Quotient(2)
   |
    <SLASH> #Quotient(1)
}

void Difference() #void:
{}
{
   LOOKAHEAD(2)
    (<MINUS> Unit()) #Difference(2)
   |
    <MINUS> #Difference(1)
}

void Sum() #void:
{}
{
   LOOKAHEAD(2)
    (<PLUS> Unit()) #Sum(2)
   |
    <PLUS> #Sum(1)
}

void Split() #void:
{}
{
   LOOKAHEAD(2)
    (<BAR> Unit()) #Split(2)
   |
    <BAR> #Split(1)
}

void Join() #void:
{}
{
   LOOKAHEAD(2)
    (<PERCENT> Unit()) #Join(2)
   |
    <PERCENT> #Join(1)
}

void Concat() #void:
{}
{
   LOOKAHEAD(2)
    (<AMP> Unit()) #Concat(2)
   |
    <AMP> #Concat(1)
}

void Assign() #void:
{}
{
   LOOKAHEAD(2)	   
   <ASSIGN> Unit() #Assign(2)	
   |
    <ASSIGN> #Undefine(1)
}

void Subscript() #void:
{}
{
   LOOKAHEAD(2)
    (<COLON> Unit()) #Subscript(2)
   |
    <COLON> #Subscript(1)
}

void AssignSubscript() #void:
{}
{
   LOOKAHEAD(2)
    (<COLON> Unit()) #AssignSubscript(2)
   |
    <COLON> #AssignSubscript(1)
}

void AssignIndexOf() #void:
{}
{
   LOOKAHEAD(2)
    (<DCOLON> Unit()) #AssignIndexOf(2)
   |
    <DCOLON> #AssignIndexOf(1)
}


void IndexOf() #void:
{}
{
   LOOKAHEAD(2)
    (<DCOLON> Unit()) #IndexOf(2)
   |
    <DCOLON> #IndexOf(1)
}

void SpecialAssign() #void:
{}
{
   (<TERM> <ASSIGN> Unit()) #TerminalOutput
  |
   (<GRAPH> <ASSIGN> Unit()) #GraphicsOutput
}


// SpatialLValues:
void SpatialVar() #void:
{}
{
    TaskVar()
   |
    EnvVar()   
}

void TaskVar() #void:
{
   Token t;
}
{
    ( t=<NODAL>
      { jjtThis.name = t.image.substring(1);} 
    ) #NodalVar
  |
    ( t=<FRONTAL>
      { jjtThis.name = t.image.substring(1);}
    ) #FrontalVar
}


void EnvVar() #void:
{}
{
    <CONTENT> #Content
  |
    <ADDRESS> #Address
  |
    <LINK> #TraveledLink
}

// RValues: syntactical elements that can only be on the right side of an
// assignment
void EnvRValue() #void:
{}
{
    <PRED> #Predecessor
  |
    <ORIENT> #Orientation
  |
    <DNEIGHBOURS> #DirectNeighbours
  |
    <INFIN> #Infinite
}


void Link() #void:
{
    Token t1 = null;
}
{
     LOOKAHEAD(2) // need local lookahead of 2 for <-> <-><3> <#> <foo>
    ( (t1=<MINUS> | t1=<PLUS>)? <ANY>
      {
	 jjtThis.dir = (t1 != null ? t1.image.charAt(0) : ' ');
      }
    ) #AnyLink
  |
    LOOKAHEAD(2) // for <DIRECT> .. vs. <DIRECT> <SEMICOLON>
    <DIRECT> #DirectLink
  |
    (
     (LOOKAHEAD( (<MINUS> | <PLUS>) (
					 (<MINUS> | <PLUS>)  // signed Number
				     |
				     StringConst()   // oriented String
				     |
				     SpatialVar()        // oriented Variable
				     )
		 )
      (t1=<MINUS> | t1=<PLUS>))? Unit() 
     {
	 jjtThis.dir = (t1 != null ? t1.image.charAt(0) : ' ');
     }
     )#NamedLink
	 
  |
    // can match empty --> last choice
    LOOKAHEAD(<DHASH>)
        {
	    jjtThis.dir = ' ';
	} #AnyLink
  |
    // can match empty --> last choice
    LOOKAHEAD(<MHASH>)
        {
	    jjtThis.dir = ' ';
	} #AnyLink
  |
    // can match empty --> last choice
    LOOKAHEAD(<PHASH>)
        {
	    jjtThis.dir = ' ';
	} #AnyLink
	   
  |
    // can match empty --> last choice
    LOOKAHEAD(<HASH>)
        {
	    jjtThis.dir = ' ';
	} #AnyLink
   
 
}

void Node() #void:
{}
{
    Unit()
  |
    <ALL> #AllNodes
  |
    // the other way to say AllNodes is actually to say nothing :)
    LOOKAHEAD(<COMMA> | <DOT> | <RPAREN> | <EOF>)
	{
	    // just to find the code in WAVEParser.java
	    boolean nothing_to_do_for_an_AllNodes;
	}#AllNodes
}

void Hop() #void:
{}
{
    Link() (
	    (<HASH> Node()) #Hop(2)
	  |
	    (<DHASH> Node()) #HopAhead(2)
	  |
	    (<MHASH> Node()) #HopMinusAhead(2)
	  |
	    (<PHASH> Node()) #HopPlusAhead(2)
	    )
}


void SimpleLiteral() #void :
{}
{
    IntConst()
  |
    StringConst()
  |
    BracketConst()
  |
    <NONE> #None
}


void ArrayLiteral() #void :
{
   Token t;
}
{
    LOOKAHEAD(2) // <"SIGN"> <SEMICOLON> vs. <"SIGN"> <INTEGER>
    SimpleLiteral()
  |
	// incomplete, only implemented things found in test cases.
	// probably needs redesign.
    (t = <NODAL> | t = <FRONTAL> | t = <DIRECT> | t = <PLUS>
     {
	 jjtThis.val = t.image;
	 jjtThis.quoted = false;
     }
    )#StringConst()
}


void IntConst():
{
   Token t1 = null;
   Token t2;
}
{
        (t1=<MINUS> | <PLUS>)? t2=<INTEGER>
	{
	    // parseInt does not want the pos. sign
	    if( t1!=null )
		jjtThis.val = - Integer.parseInt(t2.image);
	    else
		jjtThis.val = Integer.parseInt(t2.image);
	}
}

void StringConst():
{
   Token t;
}
{
    t=<STRING>
	{
	    // check for quoted/unquoted string
	    if( t.image.charAt(0) == '`' ){
		jjtThis.val = t.image.substring(1,t.image.length()-1);
		jjtThis.quoted = true;
	    }else{
		jjtThis.val = t.image;
		jjtThis.quoted = false;
	    }
	}
}

void BracketConst():
{
   Token t;
}
{
    t=<BRACKET>
	{
		jjtThis.val = t.image.substring(1,t.image.length()-1);		
	}
}

//============================================================================
// $Log: wave.jjt,v $
//
// Revision 1.45  2005/6/18 iradu
// Add POW (^) for local function call.
//
// Revision 1.44  2000/12/18 04:58:18  ksjuse
// cleanup
//
// Revision 1.43  2000/12/15 23:46:34  ksjuse
// preserve quotation of StringConsts
//
// Revision 1.42  2000/12/15 02:09:00  ksjuse
// add NONE
//
// Revision 1.41  2000/12/09 05:25:53  ksjuse
// allow non-Inv/Str elements in Array
//
// Revision 1.40  2000/12/09 04:17:15  ksjuse
// allow C/C++ style comments
//
// Revision 1.39  2000/12/09 04:04:55  ksjuse
// added DirectNeighbours
//
// Revision 1.38  2000/12/09 03:44:01  ksjuse
// added IndexOf
//
// Revision 1.37  2000/12/09 03:07:06  ksjuse
// allow "," in Repeat
//
// Revision 1.36  2000/12/01 02:36:47  ksjuse
// fail on parse problemsjunit/WaveRereadTest.java
//
// Revision 1.35  2000/11/23 04:29:52  ksjuse
// fixed typos
//
// Revision 1.34  2000/11/23 04:09:32  ksjuse
// allow "_" as first character of an unquoted string
//
// Revision 1.33  2000/11/23 03:41:48  ksjuse
// allow non-LValue to be left argument to "?" for 3?sleep
//
// Revision 1.32  2000/11/23 03:22:54  ksjuse
// removed RealConst to avoid "Nfoo=3.14159#node"-problem
//
// Revision 1.31  2000/11/21 06:15:56  ksjuse
// added HopAhead
//
// Revision 1.30  2000/11/21 05:35:32  ksjuse
// removed "Node" suffix from Literals
//
// Revision 1.29  2000/11/21 05:15:26  ksjuse
// renamed CONTENTNode and ADDRESSNODE to Content and Address
//
// Revision 1.28  2000/11/21 05:04:07  ksjuse
// added ~ and /~
//
// Revision 1.27  2000/11/21 04:44:49  ksjuse
// SpatialLValues and SpatialRValues
//
// Revision 1.26  2000/11/21 04:27:19  ksjuse
// added *, /, L and O
//
// Revision 1.25  2000/11/21 03:56:14  ksjuse
// added AS, OP and AP
//
// Revision 1.24  2000/11/20 00:04:33  ksjuse
// added OrSequential
//
// Revision 1.23  2000/11/19 23:52:50  ksjuse
// added NotEquals and IsDefined
//
// Revision 1.22  2000/11/19 23:45:13  ksjuse
// added LessThan, moved Predecessor to EnvVar
//
// Revision 1.21  2000/11/19 22:43:22  ksjuse
// added Indevisible
//
// Revision 1.20  2000/11/19 05:52:49  ksjuse
// Repeat has only one parameter
//
// Revision 1.19  2000/11/19 04:43:24  ksjuse
// added GT, EG, MINUS and PRED
//
// Revision 1.18  2000/11/19 03:51:45  ksjuse
// Terminal and Graphics are no env. variables, but are used in special assignments
//
// Revision 1.17  2000/11/08 03:51:51  ksjuse
// handle \-longlines
//
// Revision 1.16  2000/11/08 03:13:00  ksjuse
// added Create, AllNodes and Sum; orientation works with sign
//
// Revision 1.15  2000/11/07 02:35:35  ksjuse
// added SysCall and Split; simple.wave is now parsable
//
// Revision 1.14  2000/11/07 00:57:45  ksjuse
// added Assign, Undefine, Concat and Join
//
// Revision 1.13  2000/11/06 23:37:59  ksjuse
// EmptyWave works
//
// Revision 1.12  2000/11/04 04:33:54  ksjuse
// EmptyMove does not yet work
//
// Revision 1.11  2000/11/04 03:00:48  ksjuse
// restructured towards thesis grammer: +sector,action,unit;-domain,simple,composit
//
// Revision 1.10  2000/11/03 23:17:58  ksjuse
// frontal and nodal variables added
//
// Revision 1.9  2000/11/03 03:18:24  ksjuse
// added NamedLink, Hop and DIRECT
//
// Revision 1.8  2000/11/03 01:18:24  ksjuse
// shorter tree
//
// Revision 1.7  2000/11/02 18:00:28  ksjuse
// new Nodes
//
// Revision 1.6  2000/11/01 22:25:04  ksjuse
// playing with the grammar
//
// Revision 1.5  2000/11/01 21:21:31  ksjuse
// chanced AS, OS, ... to TOKENS
//
// Revision 1.4  2000/11/01 19:56:14  ksjuse
// added long and abbr. forms
//
// Revision 1.3  2000/10/31 03:48:04  ksjuse
// sample Program-grammer
//
// Revision 1.2  2000/10/30 23:41:49  ksjuse
// remove intermediatesca/ubc/cs/wave/Makefile
//
// Revision 1.1  2000/10/30 21:15:05  ksjuse
// directories refactored
//
// Revision 1.1  2000/10/30 21:04:22  ksjuse
// head&tail
//
